const glob = require('glob')
const path = require('path')
const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const mockDir = path.resolve(process.cwd(), 'mocks')
const Mock = require('mockjs')

const flatten = arr =>
  arr.reduce((acc, cur) => acc.concat(Array.isArray(cur) ? flatten(cur) : cur), [])
const responseFake = (url, type, respond) => {
  return {
    url: new RegExp(`${process.env.VUE_APP_BASE_MOCK_API}${url}`),
    type,
    response: (req, res) => {
      res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
    }
  }
}

//注册路由
function registerRouter(app) {
  let mockLastIndex
  //读取路由文件
  const routers = flatten(
    glob.sync(path.resolve(__dirname, 'modules/**/*.js')).map(item => require(item))
  )
  const routersForServer = routers.map(route => {
    return responseFake(route.url, route.type, route.response)
  })
  for (const route of routersForServer) {
    app[route.type](route.url, route.response)
    mockLastIndex = app._router.stack.length
  }
  const mockRoutesLength = Object.keys(routersForServer).length
  return {
    mockRoutesLength: mockRoutesLength,
    mockStartIndex: mockLastIndex - mockRoutesLength
  }
}

//清除require缓存
function unregisterRoutes() {
  Object.keys(require.cache).forEach(i => {
    if (i.includes(mockDir)) {
      delete require.cache[require.resolve(i)]
    }
  })
}
module.exports = function(app) {
  //解析post请求
  app.use(bodyParser.json())
  app.use(
    bodyParser.urlencoded({
      extended: true
    })
  )

  let mockRoutes = registerRouter(app)
  let mockRoutesLength = mockRoutes.mockRoutesLength
  let mockStartIndex = mockRoutes.mockStartIndex
  //监听文件变化
  let watcher = chokidar.watch(mockDir, { ignored: /index/, persistent: true })
  watcher.on('all', (event, path) => {
    if (event == 'change' || event == 'add') {
      try {
        //清除之前的路由中间件和require缓存
        app._router.stack.splice(mockStartIndex, mockRoutesLength)
        unregisterRoutes()
        //重新注册路由中间件
        let mockRoutes = registerRouter(app)
        mockRoutesLength = mockRoutes.mockRoutesLength
        mockStartIndex = mockRoutes.mockStartIndex
        console.log(`Mock Server 热更新成功! 改变的文件： ${path}`)
      } catch (err) {
        console.log(err)
      }
    }
  })
}
